package com.soupinabox;

import com.soupinabox.events.EventBroker;
import com.soupinabox.events.EventType;
import com.soupinabox.events.Event;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Collection;

/**
 * ItemPanel.java
 * <p/>
 * Author:  Taw
 * Date:    4/21/14
 */
public class ItemPanel extends JPanel {
    //Inventory inventory;

    public JPanel buildPanel;

    public JTextField hostField;
    public JTextField nameField;
    public JTextField input;
    public JButton addBtn;
    public JButton clearBtn;
    public JButton connectBtn;
    public JSlider slider;
    public JComboBox combo;
    public JLabel sizeLabel;

    boolean searching = false;

    OCRTracker ocr;

    public EventBroker broker;

    public ArrayList<Item> toBeAdded = new ArrayList<Item>();
    public ArrayList<Item> toBeRemoved = new ArrayList<Item>();

    public ItemPanel(EventBroker broker){
        super();
        this.broker = broker;
        ocr = new OCRTracker(broker);
        ocr.start();

        setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();

        JLabel lab;

        connectBtn = new JButton("Connect");
        connectBtn.setMinimumSize(connectBtn.getPreferredSize());
        c.gridx = 0;
        c.gridy = 0;
        c.gridheight = 2;
        c.insets=new Insets(0,10,0,0);
        this.add(connectBtn,c);

        lab = new JLabel("Host Username: ");
        lab.setMinimumSize(lab.getPreferredSize());
        c.gridx = 1;
        c.gridy = 0;
        c.gridheight = 1;
        c.anchor=GridBagConstraints.LINE_END;
        c.insets=new Insets(0,0,0,0);
        this.add(lab, c);

        lab = new JLabel("Inventory Name: ");
        lab.setMinimumSize(lab.getPreferredSize());
        c.gridx = 1;
        c.gridy = 1;
        this.add(lab, c);

        hostField = new JTextField(16);
        hostField.setMinimumSize(hostField.getPreferredSize());
        c.gridx = 2;
        c.gridy = 0;
        c.gridwidth=2;
        c.fill=GridBagConstraints.HORIZONTAL;
        c.anchor=GridBagConstraints.LINE_START;
        c.insets=new Insets(2,0,2,2);
        this.add(hostField, c);

        nameField = new JTextField(16);
        nameField.setMinimumSize(nameField.getPreferredSize());
        c.gridx = 2;
        c.gridy = 1;
        this.add(nameField, c);

        buildPanel = new JPanel();
        buildPanel.setLayout(new FlowLayout(FlowLayout.LEFT,-3,0));
        buildPanel.setBackground(Color.GRAY);
        c.fill = GridBagConstraints.BOTH;
        c.gridx=0;
        c.gridy=2;
        c.gridwidth=4;
        c.weightx=1;
        c.weighty=1;
        c.insets=new Insets(1,0,0,0);
        this.add(buildPanel, c);

        input = new JTextField(20);
        input.setMinimumSize(input.getPreferredSize());
        c.fill=GridBagConstraints.BOTH;
        c.gridwidth=2;
        c.weightx=0;
        c.weighty=0;
        c.gridx=0;
        c.gridy=3;
        c.insets=new Insets(2,2,0,0);
        this.add(input, c);

        addBtn = new JButton("Add");
        c.fill=GridBagConstraints.NONE;
        c.gridx=2;
        c.gridy=3;
        c.gridwidth=1;
        c.anchor=GridBagConstraints.LINE_START;
        c.insets=new Insets(2,3,0,0);
        this.add(addBtn, c);

        clearBtn = new JButton("Clear All");
        c.gridx=3;
        c.gridy=3;
        c.anchor=GridBagConstraints.LINE_START;
        c.insets=new Insets(2,3,0,0);
        this.add(clearBtn, c);

        addBtn.setPreferredSize(clearBtn.getPreferredSize());
        addBtn.setMinimumSize(addBtn.getPreferredSize());

        combo=new JComboBox();
        c.fill=GridBagConstraints.HORIZONTAL;
        c.gridwidth=2;
        c.gridx=0;
        c.gridy=4;
        c.insets=new Insets(0,2,2,0);
        this.add(combo, c);

        sizeLabel = new JLabel("40");
        c.fill=GridBagConstraints.NONE;
        c.anchor=GridBagConstraints.LINE_END;
        c.gridwidth=1;
        c.gridx=2;
        c.gridy=4;
        this.add(sizeLabel, c);

        slider = new JSlider(10, 200, 40);
        slider.setMinimumSize(slider.getPreferredSize());
        c.fill=GridBagConstraints.NONE;
        c.anchor=GridBagConstraints.LINE_START;
        c.gridwidth=1;
        c.gridx=3;
        c.gridy=4;
        this.add(slider, c);

        initListeners();

        setCombo(Item.searchFor(input.getText()));
    }

    public void initListeners(){
        input.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent e) {
                setCombo(Item.searchFor(input.getText()));
                if(!input.getText().isEmpty())combo.showPopup();
                else combo.hidePopup();
            }
            public void removeUpdate(DocumentEvent e) {
                setCombo(Item.searchFor(input.getText()));
                if(!input.getText().isEmpty())combo.showPopup();
                else combo.hidePopup();
            }
            public void insertUpdate(DocumentEvent e) {
                setCombo(Item.searchFor(input.getText()));
                if(!input.getText().isEmpty())combo.showPopup();
                else combo.hidePopup();
            }
        });

        input.addKeyListener(new KeyListener() {

            @Override
            public void keyTyped(KeyEvent e) {
                if(combo.getItemCount()>0){
                    if(e.getKeyCode()==KeyEvent.VK_ENTER){
                        broker.fireEvent(new Event(EventType.ITEM_GAINED, ((Item)combo.getSelectedItem()).index));
                        addSelectedItem();
                    } else{
                        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                            combo.setSelectedIndex(Math.min(combo.getItemCount() -1, combo.getSelectedIndex() + 1));
                        }
                        if (e.getKeyCode() == KeyEvent.VK_UP) {
                            combo.setSelectedIndex(Math.max(0, combo.getSelectedIndex() - 1));
                        }
                    }
                }
            }

            @Override
            public void keyPressed(KeyEvent e) {
                if(combo.getItemCount()>0){
                    if(e.getKeyCode()==KeyEvent.VK_ENTER){
                        addSelectedItem();
                        Item it=(Item)combo.getSelectedItem();
                        input.setText("");
                        input.requestFocus();
                        combo.setSelectedItem(it);
                    } else{
                        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                            searching=true;
                            combo.setSelectedIndex(Math.min(combo.getItemCount()-1, combo.getSelectedIndex() + 1));
                        }
                        if (e.getKeyCode() == KeyEvent.VK_UP) {
                            searching=true;
                            combo.setSelectedIndex(Math.max(0, combo.getSelectedIndex() - 1));
                        }
                    }
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {
            }
        });

        input.addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent focusEvent) {
                if(input.getCaretPosition()==0){
                    input.setCaretPosition(input.getText().length());
                }
                input.setSelectionStart(input.getCaretPosition());
                input.setSelectionEnd(input.getCaretPosition());
            }

            @Override
            public void focusLost(FocusEvent focusEvent) {

            }
        });

        KeyListener kl=new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {

            }

            @Override
            public void keyPressed(KeyEvent e) {
                if(e.getKeyCode()==KeyEvent.VK_ENTER){
                    addSelectedItem();
                    Item it=(Item)combo.getSelectedItem();
                    input.setText("");
                    input.requestFocus();
                    combo.setSelectedItem(it);
                }else if(e.getKeyChar() != KeyEvent.CHAR_UNDEFINED){
                    if(!input.hasFocus()){
                        input.setText(input.getText()+e.getKeyChar());
                    }
                    input.requestFocus();
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {

            }
        };
        combo.addKeyListener(kl);
        slider.addKeyListener(kl);
        clearBtn.addKeyListener(kl);
        addBtn.addKeyListener(kl);
        this.addKeyListener(kl);

        addBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                addSelectedItem();
                Item it=(Item)combo.getSelectedItem();
                input.setText("");
                input.requestFocus();
                combo.setSelectedItem(it);
            }
        });

        clearBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                broker.fireEvent(new Event(EventType.INVALIDATE));
                broker.fireEvent(new Event(EventType.CLEAR));
                //populateBuild();
                Item it=(Item)combo.getSelectedItem();
                input.setText("");
                input.requestFocus();
                combo.setSelectedItem(it);
            }
        });

        slider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                sizeLabel.setText(""+slider.getValue());
                //populateBuild();
            }
        });
    }

    public void addSelectedItem(){
        broker.fireEvent(new Event(EventType.ITEM_GAINED, ((Item)combo.getSelectedItem()).index));
    }


    public void setCombo(int[] ids){
        searching=true;
        combo.removeAllItems();
        //searching = true;
        for(int i=0;i<ids.length;i++){
            combo.addItem(Item.ITEMS[ids[i]]);
        }
    }

    public void populateBuild(Collection<ItemReference> build){

        buildPanel.removeAll();
        buildPanel.repaint();
        for(ItemReference ref: build){
            ItemButton btn = new ItemButton(ref,new ImageIcon((ref.item.img.getWidth()>ref.item.img.getHeight()?ref.item.img.getScaledInstance(slider.getValue(), -1, Image.SCALE_SMOOTH):ref.item.img.getScaledInstance(-1,slider.getValue(), Image.SCALE_SMOOTH))));
            btn.addActionListener(removeItemListener);
            btn.setMargin(new Insets(0, 0, 0, 0));
            btn.setBorderPainted(false);
            btn.setContentAreaFilled(false);
            btn.setFocusPainted(false);
            btn.setOpaque(false);
            btn.setPreferredSize(new Dimension(slider.getValue()+5,slider.getValue()+5));
            btn.addMouseListener(new MouseAdapter()
            {
                public void mouseEntered(MouseEvent evt)
                {
                    JButton btn = (JButton)evt.getSource();
                    btn.setBorderPainted(true);
                }
                public void mouseExited(MouseEvent evt)
                {
                    JButton btn = (JButton)evt.getSource();
                    btn.setBorderPainted(false);
                }
            });

            buildPanel.add(btn);
        }
        //buildPanel.invalidate();
        buildPanel.revalidate();
    }


    class ItemButton extends JButton {
        public ItemReference ref;
        public ItemButton(ItemReference ref,ImageIcon icon){
            super(icon);
            this.ref=ref;
        }
    }

    ActionListener removeItemListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            broker.fireEvent(new Event(EventType.ITEM_REMOVED, ((ItemButton)e.getSource()).ref.item.index));
            input.requestFocus();
        }
    };

}
